import { AfterViewInit, ChangeDetectionStrategy, Component, Injector, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ApiResToComponent } from '@basic';
import { SFSchema } from '@delon/form';
import { ArrayService } from '@delon/util';
import { BaseOfSystemForm } from '@routes/system/_base';
import { RoleForm, RoleVO } from '@types';
import { NzFormatEmitEvent, NzTreeComponent, NzTreeNode } from 'ng-zorro-antd/tree';
import { Observable } from 'rxjs';

import { SystemDictService } from '../../dict/dict.service';
import { SystemMenuService } from '../../menu/menu.service';
import { SystemRoleService } from '../role.service';

@Component({
    selector: 'app-edit-role',
    templateUrl: './edit-role.component.html',
    styleUrls: ['./edit-role.component.less'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class SystemEditRoleComponent extends BaseOfSystemForm<RoleForm, RoleVO> implements OnInit, AfterViewInit {
    validateForm: FormGroup = this.fb.group({
        roleName: ['', Validators.required],
        roleKey: ['', Validators.required],
        roleSort: [0, Validators.required],
        menuNodeAll: [false],
        menuCheckStrictly: [true],
        status: ['0'],
        menuIds: [],
        remark: ['']
    });

    @ViewChild('nzTreeComponent', { static: false }) nzTreeComponent!: NzTreeComponent;

    protected makeParams(value: any): RoleForm {
        let _temp = value;
        _temp.menuIds = this.defaultCheckedKeys;
        if (this.type === 'edit') {
            return { ..._temp, roleId: this.item.roleId };
        }
        return _temp;
    }

    statusArray: any[] = [];

    defaultCheckStrictly: boolean = true;
    defaultCheckedKeys: any[] = [];
    nodes: NzTreeNode[] = [];

    submitDisable: boolean = true;

    constructor(
        protected override injector: Injector,
        private fb: FormBuilder,
        protected roleSrv: SystemRoleService,
        protected menuSrv: SystemMenuService,
        protected arrSrv: ArrayService
    ) {
        super(injector);
    }

    override ngOnInit() {
        this.injector
            .get(SystemDictService)
            .getDicts('sys_normal_disable')
            .subscribe(res => {
                this.statusArray = res;
                this.cdRef.detectChanges();
            });
        if (this.item.roleId) {
            this.roleSrv.getRole(this.item.roleId).subscribe(res => {
                const { roleName, roleKey, roleSort, menuCheckStrictly, status, remark } = this.validateForm.controls;
                roleName.setValue(res.data?.roleName ?? '');
                roleKey.setValue(res.data?.roleKey ?? '');
                roleSort.setValue(res.data?.roleSort ?? 0);
                status.setValue(res.data?.status ?? '0');
                menuCheckStrictly.setValue(res.data?.menuCheckStrictly ?? true);
                remark.setValue(res.data?.remark ?? '');
            });
            this.menuSrv.roleMenuTreeSelect(this.item.roleId).subscribe(res => {
                this.arrSrv.visitTree(res.data?.menus ?? [], (item: any, parent) => {
                    item.title = item.label;
                    item.key = item.id;
                    item.isLeaf = !item.children;
                });
                this.nodes = res.data?.menus as any[];
                this.cdRef.detectChanges();
                this.defaultCheckedKeys = res.data?.checkedKeys ?? [];
                this.cdRef.detectChanges();
            });
        } else {
            this.menuSrv.treeSelectSF().subscribe(res => {
                this.nodes = res;
                this.cdRef.detectChanges();
            });
        }
    }

    ngAfterViewInit(): void {
        this.validateForm.get('menuNodeAll')?.valueChanges.subscribe(data => {
            let keys: any[] = [];
            if (data) {
                this.arrSrv.visitTree(this.nodes, (item, parent, level) => {
                    keys.push(item.key);
                });
            }
            this.defaultCheckedKeys = keys;
            this.cdRef.detectChanges();
        });
        this.validateForm.get('menuCheckStrictly')?.valueChanges.subscribe(data => {
            this.defaultCheckStrictly = data ?? false;
            this.cdRef.detectChanges();
        });
        this.validateForm.valueChanges.subscribe(res => {
            const { roleName, roleKey, roleSort } = this.validateForm.controls;
            if (roleName.valid && roleKey.valid && roleSort.valid) {
                this.submitDisable = false;
            } else {
                this.submitDisable = true;
            }
            this.cdRef.detectChanges();
        });
    }

    sendToServer(value: any): Observable<ApiResToComponent<RoleVO>> {
        if (this.type === 'add') {
            return this.roleSrv.addRole(value);
        }
        return this.roleSrv.updateRole(value);
    }

    nzCheck(event: NzFormatEmitEvent) {
        if (event.eventName === 'check') {
            this.defaultCheckedKeys = this.arrSrv.getKeysByTreeNode(event.nodes!, { includeHalfChecked: false });
            this.cdRef.detectChanges();
        }
    }

    submitForm() {
        this.submit(this.validateForm.value);
    }

    schema: SFSchema = {
        properties: {}
    };
}
